#ifndef _ADDRINFO_H
#define _ADDRINFO_H

#include <functional>
#include <map>
#include <unordered_map>

#include "_global.h"

// ranges
typedef std::pair<duint, duint> Range;
typedef std::pair<duint, Range> ModuleRange;           // modhash + RVA range
typedef std::pair<int, ModuleRange> DepthModuleRange;  // depth + modulerange

struct RangeCompare {
  bool operator()(const Range& a, const Range& b) const  // a before b?
  {
    return a.second < b.first;
  }
};

struct OverlappingRangeCompare {
  bool operator()(const Range& a, const Range& b) const  // a before b?
  {
    return a.second < b.first || a.second < b.second;
  }
};

struct ModuleRangeCompare {
  bool operator()(const ModuleRange& a, const ModuleRange& b) const {
    if (a.first != b.first) return a.first < b.first;  // module hash is smaller
    return a.second.second < b.second.first;  // a.second is before b.second
  }
};

struct DepthModuleRangeCompare {
  bool operator()(const DepthModuleRange& a, const DepthModuleRange& b) const {
    if (a.first != b.first) return a.first < b.first;  // module depth is
                                                       // smaller
    if (a.second.first != b.second.first)
      return a.second.first < b.second.first;  // module hash is smaller
    return a.second.second.second < b.second.second.first;  // range is smaller
  }
};

#include "serializablemap.h"

// typedefs
typedef std::function<void(duint base, const char* mod, const char* name,
                           duint addr)>
    EXPORTENUMCALLBACK;
typedef std::function<void(duint base, duint addr, const char* name,
                           const char* moduleName)>
    IMPORTENUMCALLBACK;

bool apienumexports(duint base, const EXPORTENUMCALLBACK& cbEnum);
bool apienumimports(duint base, const IMPORTENUMCALLBACK& cbEnum);

#endif  // _ADDRINFO_H
